#include "segmentacao.h"



skinRangeParam initializeGlobal () {
	skinRangeParam skinRange;
	skinRange.h_max = 136;
	skinRange.s_max = 190;
	skinRange.h_min = 91;
	skinRange.s_min = 53;
	return skinRange;
}

void applyDilateErode (IplImage *image,int e1, int d1, int e2){
    cvErode(image, image, NULL, e1);
    cvDilate(image, image, NULL, d1);
    cvErode(image, image, NULL, e2);
}

void updateSkinRange(IplImage *image, IplImage *image_bin, skinRangeParam skinRange) {
	int i,j,h,s;
	
  for (i=0;i<image->height;i++){
    for (j=0;j<image->width;j++){
      h = ((uchar *)(image->imageData + i*image->widthStep))[j*image->nChannels + 0];
      s = ((uchar *)(image->imageData + i*image->widthStep))[j*image->nChannels + 1];
      if ( (h >= skinRange.h_min) && (h <= skinRange.h_max ) && (s >= skinRange.s_min) && (s <= skinRange.s_max)) {
				((uchar *)(image_bin->imageData + i*image_bin->widthStep))[j] = 1;
      }
      else {
				((uchar *)(image_bin->imageData + i*image_bin->widthStep))[j] = 0;
      }
    }
  }
}

void computeHistogramProfiles(IplImage *image_bin, int *horizontal, int
*vertical, int vmax, int hmax) {
	int i,j;
  for (i = 0; i < vmax; i++) {
    for (j = 0; j < hmax; j++) {
			horizontal[i] += ((uchar *)(image_bin->imageData +i*image_bin->widthStep))[j];
    }
  }
  
  for (i = 0; i < hmax; i++) {
    for (j = 0; j < vmax; j++) {
			vertical[i] += ((uchar *)(image_bin->imageData + j*image_bin->widthStep))[i];
    }
  }
}

void findIntersectionPoints(int *horizontal, int tam_horizontal, int *vertical, int tam_vertical,CvPoint *points){
	int i;
	int coord_v[3], coord_h[3];
	int max_vector_h[3]={-1,-1,-1},max_vector_v[3] = {-1,-1,-1};
	
	
	int divh = (int)floor(tam_vertical/3);
	int divv = (int)floor(tam_horizontal/3);
	
	for (i = 0; i < divh; i++){
		if (max_vector_v[0] < vertical[i]) {
			max_vector_v[0] = vertical[i];
			coord_v[0] = i;
		}
		if (max_vector_v[1] < vertical[divh + 1 + i]) {
			max_vector_v[1] = vertical[divh + 1 + i];
			coord_v[1] = divh + 1 + i;
		}
		if (max_vector_v[2] < vertical[2*divh + 1 + i]) {
			max_vector_v[2] = vertical[2*divh + 1 + i];
			coord_v[2] = 2*divh + 1 + i;
		}
	}
	
	for (i = 0; i < divv; i++){
		if (max_vector_h[0] < horizontal[i]) {
			max_vector_h[0] = horizontal[i];
			coord_h[0] = i;
		}
		if (max_vector_h[1] < horizontal[divv + 1 + i]) {
			max_vector_h[1] = horizontal[divv + 1 + i];
			coord_h[1] = divv + 1 + i;
		}
		if (max_vector_h[2] < horizontal[2*divv + 1 + i]) {
			max_vector_h[2] = horizontal[2*divv + 1 + i];
			coord_h[2] = 2*divv + 1 + i;
		}
	}
	
	for (int k = 0,i = 0; i < 3; i++){
		for (int j = 0; j < 3; j++,k++) {
			points[k] = cvPoint(coord_v[j],coord_h[i]);
		}
	}
}

void choosePoints (IplImage *image_bin,CvPoint *points, CvPoint *points_chosen) {
	int i,j,k;
	int cont[9] = {0,0,0,0,0,0,0,0,0}; 
	for (k = 0; k < 9 ; k++){
		for (i = points[k].y-25; i < points[k].y + 25; i++){
			if ((i > 0) && (i < image_bin->height)){
				for (j = points[k].x-25; j < points[k].x + 25; j++){
					if ((j > 0) && (j < image_bin->width))
						cont[k]+= ((uchar *)(image_bin->imageData + i*image_bin->widthStep))[j];
				}
			}
		}
	}

	for (i = 0 ; i < 3; i++){
		int cont_aux = i;
		for (j = 1; j < 3; j++) {
			if (cont[cont_aux] < cont[3*j+i])
				cont_aux = 3*j+i;
		}
		points_chosen[i] = points[cont_aux];
	}
}

/* Inspirada na funcao do Fernando/Ana */
CvRect calculateBox (IplImage *image, CvPoint centroid) {
	int raio[8] = {0,0,0,0,0,0,0,0};

	int dimensions[4];
	bool valido = true;
	CvPoint temp;
	CvRect retorno;
	
	while (valido) {
		valido = false;
		for (int i =0; i < 8; i++) {
			temp.y = (int)ceil(centroid.y + raio[i] * sin(i*45.0*M_PI/180.0));
			temp.x = (int)ceil(centroid.x + raio[i] * cos(i*45.0*M_PI/180.0));
			if((temp.x > 0) && (temp.y > 0) &&
				 (temp.x < image->width)&&(temp.y < image->height)){
				if(((uchar *)(image->imageData + temp.y*image->widthStep))[temp.x]){
					raio[i]++;
					valido = true;
				}
			}
		}
	}
	
	// Achando as dimensoes
	dimensions[0] = MAX3(raio[7],raio[0],raio[1]);
	dimensions[1] = MAX3(raio[1],raio[2],raio[3]);
	dimensions[2] = MAX3(raio[3],raio[4],raio[5]);
	dimensions[3] = MAX3(raio[5],raio[6],raio[7]);
	
	retorno.x = centroid.x - dimensions[2];
	retorno.y = centroid.y - dimensions[3];
	retorno.width = dimensions[2] + dimensions[0];
	retorno.height = dimensions[1] + dimensions[3];
	
	// Checando se os valores estado dentro dos limites
	retorno.x = retorno.x < 0 ? 0 : retorno.x ;
	retorno.y = retorno.y < 0 ? 0 : retorno.y;
	retorno.width = (retorno.x + dimensions[2] + dimensions[0]) > image->width ? image->width - centroid.x : (dimensions[2] + dimensions[0]) ;
	retorno.height = (retorno. y + dimensions[1] + dimensions[3]) > image->height ? image->height - centroid.y : (dimensions[1] + dimensions[3]);
	
	return (retorno);
}



/*int main (void) {  
	char c;
  
	CvPoint points[9], points_chosen[3];
	CvRect boxes[3];
	
	skinRangeParam skinRange;
	IplImage *img, *img2, *imgaux; 
	
  skinRange = initializeGlobal();
  
  cvNamedWindow("HSV", CV_WINDOW_AUTOSIZE); 
  cvMoveWindow("HSV", 700, 100);
  
  cvCreateTrackbar("Max Hue","HSV",&skinRange.h_max,255,NULL);
  cvCreateTrackbar("Min Hue","HSV",&skinRange.h_min,255,NULL);
  cvCreateTrackbar("Max Saturation","HSV",&skinRange.s_max,255,NULL);
  cvCreateTrackbar("Min Saturation","HSV",&skinRange.s_min,255,NULL);
  
  //img = cvLoadImage("../../imagens/moutza_double_chiracsmall.jpg");//cvQueryFrame(capture);
  img = cvLoadImage("../../imagens/brain-hand-gestures.jpg");
	if (img == NULL)
  {
    printf("Houston! We gotta a problem!\n");
    exit(0);
  }
  
  img2 = cvCreateImage(cvGetSize(img),IPL_DEPTH_8U,1);
	imgaux = cvCreateImage(cvGetSize(img),IPL_DEPTH_8U,3);
	global = cvCreateImage(cvGetSize(img),IPL_DEPTH_8U,3);
	
	int *hist_h = new int[img->height];
	int *hist_v = new int[img->width];
	
  while(c != 'q'){

    cvCvtColor(img,imgaux,CV_RGB2HSV);
     
    updateSkinRange(imgaux,img2,skinRange);
    applyDilateErode(img2,2,5,3);
		bla(img2);
		
		if (c == 'a') {
			
			memset(hist_v, 0, sizeof(int)*img->width);
			memset(hist_h, 0, sizeof(int)*img->height);
			
			computeHistogramProfiles(img2,hist_h,hist_v,img->height,img->width);
			findIntersectionPoints(hist_h,img->height,hist_v,img->width,points);
			choosePoints(img2,points, points_chosen);
			
			for(int i=0; i < 3; i++) {
				boxes[i] = calculateBox(img2,points_chosen[i]);
				cvRectangle(global,cvPoint(boxes[i].x,boxes[i].y),cvPoint(boxes[i].x + boxes[i].width, boxes[i].y + boxes[i].height),cvScalar(0,0,255),1);
			}
			cvShowImage("Raios", global); 
		}
    
    cvShowImage("Segmentacao",global);
    cvShowImage("HSV",imgaux);
    c = cvWaitKey(10);
	  
  }
  cvReleaseImage(&img);
	cvReleaseImage(&img2);
	cvReleaseImage(&imgaux);
	cvReleaseImage(&global);
  return (0);
}*/